package seatiger.tomcat.catalina.connector;

import seatiger.tomcat.catalina.Constants;
import seatiger.tomcat.catalina.LifecycleException;
import seatiger.tomcat.coyote.Adapter;
import seatiger.tomcat.coyote.ProtocolHandler;
import seatiger.tomcat.util.StringManager;
import seatiger.tomcat.util.http.mapper.Mapper;
import seatiger.tomcat.util.http.mapper.MapperRegistry;

import java.util.concurrent.Executors;

/**
 * 新连接器，根据不同的协议，可以选择不同的ProtocolHandler
 * 默认的是 Http11Protocol
 */
public class CoyoteConnector extends AbstractConnector {
    protected ProtocolHandler protocolHandler;
    protected int port = 0;
    protected StringManager sm = StringManager.getManager(Constants.PACKAGE_CONNECTOR);
    protected String protocolHandlerClassName = "seatiger.tomcat.coyote.http11.Http11Protocol";

    //关联的adapter
    protected Adapter adapter;

    protected Mapper mapper = MapperRegistry.getInstance();


    public Mapper getMapper() {
        return this.mapper;
    }
    public CoyoteConnector() {
        this(null);
    }
    public CoyoteConnector(String protocol) {
        setProtocol(protocol);
        try {
            Class clazz = Class.forName(protocolHandlerClassName);
            this.protocolHandler = (ProtocolHandler) clazz.newInstance();
        } catch (Exception e) {
        }
    }

    /**
     * 根据不同的协议选择不同的protocolHandlerClassName
     * @param protocol
     */
    public void setProtocol(String protocol) {
        if (protocol != null) {
            protocolHandlerClassName = protocol;
        }
    }

    public void setPort(int port) {
        this.port = port;
    }

    /**
     * 初始话连接器，创建serverSocket
     *
     * @throws LifecycleException
     */
    @Override
    public void initialize() throws LifecycleException {
        if (initialized) {
            return;
        }
        initialized = true;
        try {
            protocolHandler.setExecutor(Executors.newCachedThreadPool());
            protocolHandler.setPort(port);
            adapter = new CoyoteAdapter(this);
            protocolHandler.setAdapter(adapter);
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException
                    (sm.getString
                            ("coyoteConnector.protocolHandlerInitializationFailed", e));
        }
    }

    @Override
    public void start() throws LifecycleException {
        if (!initialized) {
            initialize();
        }
        if (started) {
            return;
        }
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;
        try {
            protocolHandler.start();
        } catch (Exception e) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerStartFailed", e));
        }
    }

    @Override
    public void stop() throws LifecycleException {
        if (!started) {
            return;
        }
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
        try {
            protocolHandler.destroy();
        } catch (Exception e) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerDestroyFailed", e));
        }
    }

    public NewRequest createNewRequest() {
        NewRequest newRequest = new NewRequest();
        newRequest.setConnector(this);
        return newRequest;
    }

    public NewResponse createNewResponse() {
        NewResponse newResponse = new NewResponse();
        newResponse.setConnector(this);
        return newResponse;
    }
}
